#region Copyright
/// <copyright>
/// Copyright (c) 2007 Ilia Shramko.
/// Released under the terms of the GNU General Public License.
/// </copyright>
#endregion

using System;
using System.Collections.Generic;
using System.Text;

namespace Osh
{
	public static class HexConverter
	{
		public static void ToHex(byte v, char[] chars, int offset)
		{
			byte b1 = (byte)(v >> 4);
			byte b2 = (byte)(v & 0xF);

			chars[offset] = (char)(b1 > 9 ? b1 + 0x37 : b1 + 0x30);
			chars[offset+1] = (char)(b2 > 9 ? b2 + 0x37 : b2 + 0x30);
		}

		public static void ToHex(ushort v, char[] chars, int offset)
		{
			ToHex((byte)(v >> 8), chars, offset);
			ToHex((byte)(v & 0xFF), chars, offset + 2);
		}
		
		public static void ToHex(uint v, char[] chars, int offset)
		{
			ToHex((ushort)(v >> 16), chars, offset);
			ToHex((ushort)(v & 0xFFFF), chars, offset + 4);
		}

		public static void ToHex(ulong v, char[] chars, int offset)
		{
			ToHex((uint)(v >> 32), chars, offset);
			ToHex((uint)(v & 0xFFFFFFFF), chars, offset + 8);
		}


		public static void ToHexBE(ushort v, char[] chars, int offset)
		{
			ToHex((byte)(v & 0xFF), chars, offset);
			ToHex((byte)(v >> 8), chars, offset + 2);
		}
		

		public static void ToHexBE(uint v, char[] chars, int offset)
		{
			ToHexBE((ushort)(v & 0xFFFF), chars, offset);
			ToHexBE((ushort)(v >> 16), chars, offset + 4);
		}

		public static void ToHexBE(ulong v, char[] chars, int offset)
		{
			ToHexBE((uint)(v & 0xFFFFFFFF), chars, offset);
			ToHexBE((uint)(v >> 32), chars, offset + 8);
		}

		
		public static byte ToByte(string str, int offset)
		{
			return (byte)((FromHex(str[offset]) << 4) | FromHex(str[offset + 1]));
		}

		public static ushort ToUInt16(string str, int offset)
		{
			return (ushort)((ToByte(str, offset) << 8) | ToByte(str, offset + 2));
		}
		
		public static uint ToUInt32(string str, int offset)
		{
			return (uint)((ToUInt16(str, offset) << 16) | ToUInt16(str, offset + 4));
		}

		public static ulong ToUInt64(string str, int offset)
		{
			return (ulong)((((ulong)ToUInt32(str, offset)) << 32) | ToUInt32(str, offset + 8));
		}


		public static ushort ToUInt16BE(string str, int offset)
		{
			return (ushort)(ToByte(str, offset) | (ToByte(str, offset + 2) << 8));
		}

		public static uint ToUInt32BE(string str, int offset)
		{
			return (uint)(ToUInt16BE(str, offset) | (ToUInt16BE(str, offset + 4) << 16));
		}

		public static ulong ToUInt64BE(string str, int offset)
		{
			return (ulong)(ToUInt32BE(str, offset) | (ToUInt32BE(str, offset + 8) << 32));
		}


		public static int FromHex(int ch)
		{
			if(ch >= 0x30 && ch <= 0x39) return ch - 0x30;
			if(ch >= 0x41 && ch <= 0x46) return ch - 0x37;
			if(ch >= 0x61 && ch <= 0x66) return ch - 0x57;

			throw new ArgumentOutOfRangeException("ch");
		}
	}
}
